Skip to content

test: assert the consequence, not the setter round-trip - #1925

Merged
laurentiu021 merged 1 commit into
mainfrom
test/replace-pure-echo-assertions
Aug 18, 2026
Merged

test: assert the consequence, not the setter round-trip#1925
laurentiu021 merged 1 commit into
mainfrom
test/replace-pure-echo-assertions

Conversation

@laurentiu021

Copy link
Copy Markdown
Owner

What this is

A mechanical sweep for pure-echo tests — set a property, assert that same property, no production
call in between — found 15 in the suite:

[Fact]
public void OsLine_Setter_Works()
{
    var vm = NewVm();
    vm.OsLine = "Windows 11 Pro";
    Assert.Equal("Windows 11 Pro", vm.OsLine);   // round-trips a generated setter
}

Every one of these exercises the CommunityToolkit [ObservableProperty] source generator, not this
codebase. They cannot fail on a real defect, and they inflate the test count and the confidence that
number implies. Backlog item #127.

The backlog guessed ~50% false positives. Triaging each one against current source gave a different
and more useful split.

Replaced — the consequence was real and asserted nowhere (5)

Both FilterText properties are wired (OnFilterTextChanged → ApplyFilter), and ApplyFilter
rebuilds the collection the DataGrid binds to. The echo tests never looked at it. A filter wired to
nothing is a defect this project has already shipped — batch 30, five unreachable Services filters
and the old assertion could not have caught it. Now asserted:

Claim Test
the bound list narrows, and clearing restores it ProcessManager…FilterText_NarrowsTheBoundList
PID and description match too, not just the name ProcessManager…FilterText_AlsoMatchesPidAndDescription
list narrows and AppCount + the "(of N total)" summary follow Uninstaller…NarrowsTheListAndCorrectsTheCountAndSummary
the package Id matches, not just the display name Uninstaller…FilterText_AlsoMatchesThePackageId

FriendlyEventEntry extreme timestamps — storing MinValue/MaxValue proved a DateTime field
holds a DateTime. The reachable question is what RelativeTime and FullTimestamp do with them,
because RelativeTime subtracts from DateTime.Now, so a future stamp produces a negative span.
Behaviour is pinned as-is (MinValue → em dash, future → "just now") plus an assertion that no negative
duration can reach the user if those branches are ever reordered. Deliberately not "fixed": "just now"
for a clock-corrected event is imprecise but harmless, and far better than printing "in -3d".

Removed — nothing left to assert (9), each verified case by case

  • Dashboard OsLine/UptimeLine/CpuPercent/RamPercent _Setter_Works — notification is what a
    binding depends on, and Setter_FiresPropertyChanged already covers it. The two percentages were
    missing from that theory, so they were added to it (parameter widened to object) rather than
    simply dropped.
  • Cleanup TempSizeLabel/RecycleBinLabel _CanBeSetDirectly — covered by _DefaultIsScanning
    and PreScan_EventuallyPopulatesLabels.
  • Cleanup Progress_AcceptsFullRange — the name implied a 0-100 contract nothing enforces
    (ViewModelBase._progress is unclamped; the ProgressBar clamps visually).
  • Performance SelectedPlan_CanBeChanged — default and notification both already covered.
  • AppPackage.Status_Transitions_ArePossible, PingTarget.Stats_CanBeUpdated — model echoes with
    no computed members over them.
  • DuplicateFile.MinSizeKb_CanBeChanged — its real consequence is minBytes = MinSizeKb * 1024 in
    ScanAsync, and asserting that needs a guard the code does not have: a large typed value overflows
    long and inverts the filter (asking for "≥ 9 quadrillion KB" returns everything). Tracked
    separately so this change stays behaviour-neutral.

Verification

Red proof: 6 mutations, all 3 touched source files restored byte-for-byte. Every replacement goes
red when its claim is broken — which is the whole point, since the tests it replaced could not go red
at all:

Mutation Must go red
unwire ProcessManager.OnFilterTextChanged (the batch-30 defect) both ProcessManager filter tests
unwire Uninstaller.OnFilterTextChanged both Uninstaller filter tests
MatchesPid always false the PID/description test
Uninstaller stops matching Id the package-Id test
Summary drops the "(of N total)" qualifier the count/summary test
let a negative span fall past the "just now" branch the extreme-timestamp test

No production code changed. All four projects build 0 errors / 0 warnings;
dotnet format --verify-no-changes exit 0; author headers intact on all 9 files; leak scan over all 32
terms gives 0 hits. Net -9 [Fact]/[Theory] attributes (14 removed, 5 added) plus 2 new theory
rows, so the CI count should read 4689. test: — no version bump, no release.

A mechanical sweep for "pure echo" tests — set a property, assert the same
property, no production call in between — found 15 in the suite. Each one round
-trips a generated [ObservableProperty] setter, so the only way it can fail is if
the CommunityToolkit source generator breaks. They cannot catch a defect in this
codebase, while inflating the test count and the confidence it implies.

Triaged one at a time; the split was NOT the ~50% the backlog guessed.

REPLACED (4 tests) — the consequence was real and asserted nowhere:

* ProcessManager and Uninstaller FilterText. Both have
  OnFilterTextChanged -> ApplyFilter, which rebuilds the collection the DataGrid
  binds to; the echo tests never touched it. A filter wired to nothing is a defect
  this project has already shipped (batch 30, five unreachable Services filters)
  and the old assertions could not have caught it. Now asserted: the bound list
  narrows, clearing restores it, PID and description match for processes, package
  Id matches for apps, and the Uninstaller's AppCount and "(of N total)" summary
  follow.

REPLACED (1 test) — the interesting question was one level up:

* FriendlyEventEntry extreme timestamps. Storing MinValue/MaxValue proved a
  DateTime field holds a DateTime. What matters is what RelativeTime and
  FullTimestamp DO with them, since RelativeTime subtracts from DateTime.Now: a
  future stamp yields a NEGATIVE span. Behaviour pinned as-is (MinValue -> em dash,
  future -> "just now"), plus an assertion that no negative duration can ever
  reach the user if those branches are reordered.

REMOVED (9 tests) — nothing left to assert, and the real behaviour is already
covered elsewhere, verified case by case:

* Dashboard OsLine/UptimeLine/CpuPercent/RamPercent "_Setter_Works" — notification
  is what a binding depends on, and Setter_FiresPropertyChanged covers it; the two
  percentages were missing from it, so they were added (its parameter widened to
  object) rather than dropped.
* Cleanup TempSizeLabel/RecycleBinLabel "_CanBeSetDirectly" — covered by
  _DefaultIsScanning and PreScan_EventuallyPopulatesLabels.
* Cleanup Progress_AcceptsFullRange — the name implied a 0-100 contract nothing
  enforces (ViewModelBase._progress is unclamped).
* Performance SelectedPlan_CanBeChanged — default and notification both covered.
* AppPackage Status_Transitions_ArePossible, PingTarget Stats_CanBeUpdated —
  model echoes with no computed members over them.
* DuplicateFile MinSizeKb_CanBeChanged — its real consequence is
  `minBytes = MinSizeKb * 1024`, which needs a guard the code lacks (a large typed
  value overflows long and inverts the filter). Tracked separately so this stays
  behaviour-neutral.

Red proof: 6 mutations, all 3 touched source files restored byte-for-byte. Every
replacement goes red when its claim is broken — unwiring either filter, breaking
the PID or Id match, dropping the summary qualifier, or letting a negative span
past the "just now" branch. No production code changed; net -9 [Fact]/[Theory].
@laurentiu021
laurentiu021 merged commit 7288a93 into main Aug 18, 2026
5 checks passed
@laurentiu021
laurentiu021 deleted the test/replace-pure-echo-assertions branch August 18, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant